using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using RJB.S3.Entities;

namespace RJB.S3Library
{
    //A public enum of all the methods 
    //that this library supports
    public enum AmazonMethods
    {
            CreateBucket,
            ListBucket,
            DeleteBucket,
            PutObjectInline,
            GetObject,
            DeleteObject,
            GetObjectAccessControlPolicy,
            GetBucketAccessControlPolicy,
            SetObjectAccessControlPolicy,
            SetBucketAccessControlPolicy,
            ListAllMyBuckets
    }
    
    public abstract class Manager
    {
        
        private string _userKey;
        private string _secretKey;

        //The format that S3 expects the timestamp to be in.
        private const string ISODateFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
        //All signatures need to be prepended by this string
        private const string AmazonS3 = "AmazonS3";

        private List<EntityBase> _cache;
        
        public string UserKey
        {
            get { return _userKey; }
            set { _userKey = value;}
        }
        public string SecretKey
        {
            get { return _secretKey;}
            set { _secretKey = value;}
        }
        
        //TODO:
        //We need to support caching in the files or folders
        internal List<EntityBase> Cache
        {
            get { return _cache; }
            set { _cache = value; }
        }
        
        public Manager(string UserKey, string SecretKey)
        {
            this.UserKey = UserKey;
            this.SecretKey = SecretKey;
            _cache = new List<EntityBase>();
        }
        
        /// <summary>
        /// This retrieves the current timestamp to be used for the signature
        /// </summary>
        /// <returns>The timestamp</returns>
        public static DateTime CurrentTimeStamp()
        {
            DateTime _curr = DateTime.Now;
            DateTime _friendly;

            _friendly = new DateTime(_curr.Year, _curr.Month, _curr.Day, _curr.Hour, _curr.Minute, _curr.Second, _curr.Millisecond, DateTimeKind.Local);
            return _friendly;
        }
        /// <summary>
        /// Converts the timestamp to ISO format
        /// </summary>
        /// <param name="TimeStamp"></param>
        /// <returns></returns>
        private static string ISOTimeStamp(DateTime TimeStamp)
        {
            return TimeStamp.ToUniversalTime().ToString(ISODateFormat, System.Globalization.CultureInfo.InvariantCulture);
        }
        /// <summary>
        /// This method generates the necessary signature for the S3 service
        /// </summary>
        /// <param name="Operation">The operation that will take place.</param>
        /// <param name="TimeStamp">The timestamp for the operation</param>
        /// <returns>A Base 64 representation of the signature</returns>
        public string GenerateSignature(AmazonMethods Operation, DateTime TimeStamp)
        {
            string _sigRaw;
            UTF8Encoding _encoder = new UTF8Encoding();

            HMACSHA1 _hma;
            _sigRaw = AmazonS3 + Operation.ToString() + ISOTimeStamp(TimeStamp);

            _hma = new HMACSHA1(_encoder.GetBytes(this.SecretKey));
            return Convert.ToBase64String(_hma.ComputeHash(_encoder.GetBytes(_sigRaw.ToCharArray())));
        }
    }
}
